package cn.org.wangchangjiu.redis.application.nearby;

import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.ArrayList;
import java.util.List;

/**
 * @author wangchangjiu
 * @Classname StringRedisGeoNearBy
 * @Description geo 附近的（人/车）
 * @Date 2023/12/16 18:29
 */
public class StringRedisGeoNearBy {

    private StringRedisTemplate redisTemplate;

    public StringRedisGeoNearBy(StringRedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     *  添加位置
     * @param key
     * @param longitude
     * @param latitude
     * @param member
     * @return
     */
    public Boolean geoAdd(String key, double longitude, double latitude, String member) {
        Long num = redisTemplate.opsForGeo().add(key, new Point(longitude, latitude), member);
        return num != null;
    }

    public List<GeoRadiusDto> radius(GeoRadiusQueryDto geoRadiusQuery) {
        Circle circle = new Circle(
                new Point(geoRadiusQuery.getLongitude(), geoRadiusQuery.getLatitude()),
                new Distance(geoRadiusQuery.getValue(), geoRadiusQuery.getMetric()));

        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                .includeDistance().includeCoordinates();

        if (geoRadiusQuery.getSort() == 1) {
            args.sortDescending();
        } else {
            args.sortAscending();
        }

        args.limit(geoRadiusQuery.getLimit() > 0 ? geoRadiusQuery.getLimit() : 10);

        GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo().radius(geoRadiusQuery.getKey(), circle, args);

        List<GeoRadiusDto> result = new ArrayList<>();

        if (results == null) {
            return result;
        }

        for (GeoResult<RedisGeoCommands.GeoLocation<String>> geoResult : results) {
            GeoRadiusDto geoRadiusDto = new GeoRadiusDto();
            geoRadiusDto.setName(String.valueOf(geoResult.getContent().getName()));
            geoRadiusDto.setLongitude(geoResult.getContent().getPoint().getX());
            geoRadiusDto.setLatitude(geoResult.getContent().getPoint().getY());
            geoRadiusDto.setValue(geoResult.getDistance().getValue());
            result.add(geoRadiusDto);
        }

        return result;
    }

    public Double distance(String key, String member1, String member2, Metric metric) {
        Distance distance = redisTemplate.opsForGeo().distance(key, member1, member2, metric);
        return distance == null ? -1 : distance.getValue();
    }


    public List<GeoRadiusDto> radiusByMember(GeoRadiusQueryDto geoRadiusQuery) {

        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                .includeDistance().includeCoordinates();

        if (geoRadiusQuery.getSort() == 1) {
            args.sortDescending();
        } else {
            args.sortAscending();
        }

        args.limit(geoRadiusQuery.getLimit() > 0 ? geoRadiusQuery.getLimit() : 10);


        GeoResults<RedisGeoCommands.GeoLocation<String>> results =
                redisTemplate.opsForGeo().radius(geoRadiusQuery.getKey(), geoRadiusQuery.getMember(),
                        new Distance(geoRadiusQuery.getValue(), geoRadiusQuery.getMetric()), args);

        List<GeoRadiusDto> result = new ArrayList<>();

        if (results == null) {
            return result;
        }

        for (GeoResult<RedisGeoCommands.GeoLocation<String>> geoResult : results) {
            GeoRadiusDto geoRadiusDto = new GeoRadiusDto();
            geoRadiusDto.setName(String.valueOf(geoResult.getContent().getName()));
            geoRadiusDto.setLongitude(geoResult.getContent().getPoint().getX());
            geoRadiusDto.setLatitude(geoResult.getContent().getPoint().getY());
            geoRadiusDto.setValue(geoResult.getDistance().getValue());
            result.add(geoRadiusDto);
        }

        return result;
    }




}
